<?php

namespace app\controller;

use app\BaseController;
use think\facade\View;
use think\facade\Db;
use think\facade\Cache;
use think\facade\Session;
use think\facade\Request;
use think\model\Collection;

use app\controller\model\ExppacDaiquorder;
use app\controller\model\ExppacMember;
use app\controller\model\CountUsers;
use app\controller\model\CountOrders;

class Index extends BaseController
{
    // 每页获取的数据量
    protected $pageSize = 100;

    public function index($token="",$open="")
    {
        // 读取env 设置token码
        $tokenCheck = env('TOKEN');
        if ($token != $tokenCheck) {
            return json(['code'=>404]);
        }

        $isLoggedIn = Session::get('is_logged_in');
        // return json($isLoggedIn);

        // 输出模板
        View::assign('isLoggedIn',$isLoggedIn);
        View::assign('open',$open);
        return View::fetch();
    }

    /**
     * 独立缓存数据函数
     *
     * @param string   $cacheKey 缓存键名
     * @param callable $callback  如果缓存不存在时，用于生成数据的回调函数
     * @param int      $ttl       缓存时间，单位秒，默认一天
     * @param bool     $forceRefresh 是否强制刷新缓存，默认为 false
     *
     * @return mixed 缓存数据
     */
    protected function getCachedData(string $cacheKey, callable $callback, int $ttl = 86400, bool $forceRefresh = false)
    {
        if (!$forceRefresh && Cache::has($cacheKey)) {
            // 缓存存在且不需要强制刷新，直接返回缓存数据
            return Cache::get($cacheKey);
        } else {
            // 缓存不存在或需要强制刷新，执行回调函数获取数据
            $data = $callback();

            // 缓存数据
            Cache::set($cacheKey, $data, $ttl);

            return $data;
        }
    }

    // 获取用户分布数据 (示例，可以按城市统计)
    public function getCity()
    {
        $startTime = Request::param('start_time');
        $endTime = Request::param('end_time');
        $isLoggedIn = Session::get('is_logged_in');

        // 构建缓存键
        $cacheKey = 'getCityData_' . ($isLoggedIn ? 'logged_in' : 'logged_out');
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            $cacheKey .= '_' . md5($startTime . $endTime);
        }

        $distribution = $this->getCachedData($cacheKey, function () use ($isLoggedIn, $startTime, $endTime) {
            $query = ExppacDaiquorder::field('des, buildschoolname, count(*) as count');

            // 根据登录状态决定查询条件
            if (!$isLoggedIn) {
                $query->where('status', 5)
                    ->whereNotNull('lat1')
                    ->whereNotNull('lng1');
            }

            // 添加时间范围查询
            if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
                $startTime = strtotime($startTime);
                $endTime = strtotime($endTime);
                $query->where('addtime', '>=', $startTime)
                      ->where('addtime', '<', $endTime);
            }

            $distribution = $query->group('des, buildschoolname')
                                ->select()
                                ->toArray();

            usort($distribution, function ($a, $b) {
                return $b['count'] - $a['count'];
            });

            return $distribution;
        }, 86400);

        return json($distribution);
    }


   public function getAddress()
    {
        $startTime = Request::param('start_time');
        $endTime = Request::param('end_time');
        $isLoggedIn = Session::get('is_logged_in');

        // 构建缓存键
        $cacheKey = 'getAddressData_' . ($isLoggedIn ? 'logged_in' : 'logged_out');
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            $cacheKey .= '_' . md5($startTime . $endTime);
        }

        $mapsData = $this->getCachedData($cacheKey, function () use ($isLoggedIn, $startTime, $endTime) {
            $mapsData = [];
            $page = 1;
            $result = [];

            do {
                $daiquorder = ExppacDaiquorder::where('status', 5)
                    ->where('lat1', '<>', 'null');

                // 添加时间范围查询
                if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
                    $startTime = strtotime($startTime);
                    $endTime = strtotime($endTime);
                    $daiquorder->where('addtime', '>=', $startTime)
                              ->where('addtime', '<', $endTime);
                }

                $daiquorder = $daiquorder->page($page, $this->pageSize)
                    ->select();

                // 如果没有数据了，就跳出循环
                if ($daiquorder->isEmpty()) {
                    break;
                }

                // 遍历结果集
                foreach ($daiquorder as $value) {
                    $item = [
                        'lat' => $value['lat1'],
                        'lng' => $value['lng1'],
                        'lat_lng'=> $value['lat1'] . ',' . $value['lng1'],
                        'address' => $value['buildschoolname'] . $value['des'],
                        'address_detail' => $value['des2'],
                    ];

                    if ($isLoggedIn) {
                        $item = array_merge([
                            'id' => $value['id'],
                            'name' => $value['fname'],
                            'phone' => $value['ftel'],
                        ], $item);
                    }
                    $result[] = $item;
                }

                $page++; // 下一页
            } while (true);
            return $result;
        }, 86400);

        return json($mapsData);
    }

    // 密码验证
    public function login()
    {
        $admin_password=env('ADMIN_PASSWORD');
        $password = Request::param('password');
        // 假设正确的密码是 "admin123"
        if ($password === $admin_password) {
            // 密码验证成功，设置 Session 登录状态
            Session::set('is_logged_in', true);
            return json(['code' => 200, 'msg' => '登录成功']);
        } else {
            // 密码验证失败
            return json(['code' => 401, 'msg' => '密码错误']);
        }
    }
    // 退出登录
    public function logout()
    {
        // 清除 Session 登录状态
        Session::delete('is_logged_in');
        return json(['code' => 200, 'msg' => '退出成功']);
    }



    /**
     * 新用户统计
     *
     */
    public function newUser()
    {
        $startTime = Request::param('start_time');
        $endTime = Request::param('end_time');

        // 构建缓存键
        $cacheKey = 'newUser';
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            $cacheKey .= '_' . md5($startTime . $endTime);
        } else {
            $cacheKey .= '_' . date('Ymd'); // 默认缓存键
        }

        $cachedData = Cache::get($cacheKey);

        if ($cachedData) {
            // 缓存命中，直接返回缓存数据
            return json(['code' => 200, 'msg' => '查询成功(Cache)', 'data_time' => date('Y-m-d', strtotime('-1 day')), 'data' => $cachedData]);
        }

        // 缓存未命中，执行查询
        $currentTime = time();
        $todayTime = strtotime(date('Y-m-d', $currentTime));
        $yesterdayTime = strtotime(date('Y-m-d', $currentTime - 86400));

        $newUserList = ExppacMember::with('bindschool');

        // 添加时间范围查询
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            $startTime = strtotime($startTime);
            $endTime = strtotime($endTime);
            $newUserList->where('addtime', '>=', $startTime)
                      ->where('addtime', '<', $endTime);
        } else {
            $newUserList->where('addtime', '>=', $yesterdayTime)
                      ->where('addtime', '<', $todayTime);
        }

        $newUserList = $newUserList->field('openid,avatar,addtime,nickname,parentid,user_code,bindschool')
            ->select()
            ->toArray();


        // 按bindschool分组统计数量
        $countUsers = array_reduce($newUserList, function ($result, $item) {
            if (isset($item['bindschool']['id'])) {
                $schoolId = $item['bindschool']['id'];
                $result[$schoolId][] = $item;
            }else{
                $result[0][] = $item;
            }
            return $result;
        }, []);

        
        
        $countUsers2 = array_map(function ($schoolId, $users) {
            $schoolName = $users[0]['bindschool']['name'] ?? '未绑定';
            $count = count($users);
            return [
                'tid' => $schoolId,
                'tname' => $schoolName,
                'new_users_count' => $count,
                'date' =>  date('Y-m-d', time() - 86400),
            ];
        }, array_keys($countUsers), array_values($countUsers));

        // 保存统计结果到数据库
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            // 开始事务写入
            Db::startTrans();
            try {
            // 使用悲观锁
                $existingData = CountUsers::where('date', date('Y-m-d'))
                ->lock(true) // 添加排他锁
                ->find();

                if ($existingData) {
                    CountUsers::where('date', date('Y-m-d'))->delete();
                }

                CountUsers::insertAll($countUsers2);
                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
                return json(['code' => 500, 'msg' => '保存统计结果到数据库失败: ' . $e->getMessage()]);
            }
        }

        // 将数据存入缓存，有效期1天 (86400秒)
        Cache::set($cacheKey, $countUsers2, 86400);

        return json(['code' => 200, 'msg' => '查询成功', 'data_time' => date('Y-m-d',  strtotime('-1 day')), 'data' => $countUsers2]);
    }

    /**
     * 昨日订单统计
     */
    public function getOrder()
    {
        $startTime = Request::param('start_time');
        $endTime = Request::param('end_time');

        // 构建缓存键
        $cacheKey = 'yesterdayOrder';
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            $cacheKey .= '_' . md5($startTime . $endTime);
        } else {
            $cacheKey .= '_' . date('Ymd'); // 默认缓存键
        }

        $cachedData = Cache::get($cacheKey);

        if ($cachedData) {
            // 缓存命中，直接返回缓存数据
            return json(['code' => 200, 'msg' => '查询成功(Cache)', 'data_time' => date('Y-m-d', strtotime('-1 day')), 'data' => $cachedData]);
        }

        // 缓存未命中，执行查询
        $yesterdayTime = strtotime('yesterday'); // 获取昨天凌晨的时间戳
        $todayTime = strtotime('today'); // 获取今天凌晨的时间戳

        $yesterdayOrderList = ExppacDaiquorder::with('bindschool');

        // 添加时间范围查询
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            $startTime = strtotime($startTime);
            $endTime = strtotime($endTime);
            $yesterdayOrderList->where('addtime', '>=', $startTime)
                              ->where('addtime', '<', $endTime);
        } else {
            $yesterdayOrderList->where('addtime', '>=', $yesterdayTime)
                              ->where('addtime', '<', $todayTime);
        }

        $yesterdayOrderList = $yesterdayOrderList->where('status', '=', 5)
            ->field('id,fname,addtime,buildschool,openid,ordernum,buildschoolname,status,stationtext,des')
            ->select()
            ->toArray();

        $yesterdayOrderList2 = array_map(function ($item) {
            $item['addtime'] = date('Y-m-d H:i:s', $item['addtime']);
            return $item;
        }, $yesterdayOrderList);

        $yesterdayOrderList3 = array_reduce($yesterdayOrderList2, function ($result, $item) {
            $schoolId = $item['buildschool'];
            if (!isset($result[$schoolId])) {
                $result[$schoolId] = []; // 初始化数组，避免后续push报错
            }
            $result[$schoolId][] = $item;
            return $result;
        }, []);

        $yesterdayOrderList4 = array_map(function ($schoolId, $orders) use ($yesterdayTime) {
            $schoolName = isset($orders[0]['buildschoolname']) ? $orders[0]['buildschoolname'] : '未绑定'; // 修复数组可能为空的问题
            $count = count($orders);
            return [
                'tid' => $schoolId,
                'tname' => $schoolName,
                'yesterday_order_count' => $count,
                'date' => date('Y-m-d', $yesterdayTime),
            ];
        }, array_keys($yesterdayOrderList3), $yesterdayOrderList3);

        $yesterdayOrderList5 = array_values($yesterdayOrderList4);
        
        // 添加区域订单历史数据表写入逻辑
        if ($startTime && $endTime && strtotime($startTime) && strtotime($endTime)) {
            try {
                // 开始事务写入
                Db::startTrans();

                // 使用悲观锁
                $existingData = CountOrders::where('date', date('Y-m-d', $yesterdayTime))
                    ->lock(true) // 添加排他锁
                    ->find();

                if ($existingData) {
                    CountOrders::where('date', date('Y-m-d', $yesterdayTime))->delete();
                }

                // 批量插入数据，假设$yesterdayOrderList5是待插入的数据
                CountOrders::insertAll($yesterdayOrderList5);

                Db::commit();

            } catch (\Exception $e) {
                Db::rollback();
                return json(['code' => 500, 'msg' => '保存统计结果到数据库失败: ' . $e->getMessage()]);
            }
        }

        // 存储缓存
        Cache::set($cacheKey, $yesterdayOrderList5, 86400); // 缓存一天

        return json(['code' => 200, 'msg' => '查询成功', 'data_time' => date('Y-m-d', strtotime('-1 day')), 'data' => $yesterdayOrderList5]);

    }

    /**
     * 添加区域订单历史数据表
     * @param $tid
     * @return \think\response\Json
     */
    public function getOrderHistory($tid)
    {
        $startTime = Request::param('start_time');
        $endTime = Request::param('end_time');

        // 构建缓存键
        $cacheKey = 'orderHistory_' . $tid;
        if ($startTime && $endTime) {
            $cacheKey .= '_' . md5($startTime . $endTime);
        }

        $cachedData = Cache::get($cacheKey);
        if ($cachedData) {
            // 缓存命中，直接返回缓存数据
            return json(['code' => 200, 'msg' => '查询成功(Cache)', 'data_time' => date('Y-m-d', strtotime('-1 day')), 'data' => $cachedData]);
        }

        // 缓存未命中，执行查询
        $orderHistory = CountOrders::where('tid', $tid);

        // 添加时间范围查询
        if ($startTime && $endTime) {
            $orderHistory->whereBetween('date', [$startTime, $endTime]);
        }

        $orderHistory = $orderHistory->select()->toArray();

        // 输出用于ECharts的数据格式
        $orderHistory = array_map(function ($item) {
            return [
                'date' => $item['date'],
                'count' => $item['yesterday_order_count'],
            ];
        }, $orderHistory);

        // 存储缓存
        Cache::set($cacheKey, $orderHistory, 86400);

        return json(['code' => 200, 'msg' => '查询成功', 'data_time' => date('Y-m-d', strtotime('-1 day')), 'data' => $orderHistory]);
    }

    /**
     * 用户新增历史统计
     * @param $tid
     * @return \think\response\Json
     */
    public function getNewUserHistory($tid)
    {
        $startTime = Request::param('start_time');
        $endTime = Request::param('end_time');

        // 构建缓存键
        $cacheKey = 'newUser_' . $tid;
        if ($startTime && $endTime) {
            $cacheKey .= '_' . md5($startTime . $endTime);
        }

        $cachedData = Cache::get($cacheKey);
        if ($cachedData) {
            // 缓存命中，直接返回缓存数据
            return json(['code' => 200, 'msg' => '查询成功(Cache)', 'data_time' => date('Y-m-d', strtotime('-1 day')), 'data' => $cachedData]);
        }

        // 缓存未命中，执行查询
        $userHistory = CountUsers::where('tid', $tid);

        // 添加时间范围查询
        if ($startTime && $endTime) {
            $userHistory->whereBetween('date', [$startTime, $endTime]);
        }

        $userHistory = $userHistory->select()->toArray();

        // 输出用于ECharts的数据格式
        $userHistory = array_map(function ($item) {
            return [
                'date' => $item['date'],
                'count' => $item['new_users_count'],
            ];
        }, $userHistory);

        // 存储缓存
        Cache::set($cacheKey, $userHistory, 86400);

        return json(['code' => 200, 'msg' => '查询成功', 'data_time' => date('Y-m-d', strtotime('-1 day')), 'data' => $userHistory]);
    }


    /**
     * 刷新所有缓存接口 (City、Address、Order、NewUser)
     *
     * @return \think\response\Json
     */
    public function refreshAllCache()
    {
        // 清空所有缓存
        $this->clearCache();

        // 刷新 city 缓存
        $this->getCity();

        // 刷新 address 缓存
        $this->getAddress();
        $this->getOrder();
        $this->newUser();

        return json(['code' => 200, 'msg' => '所有缓存已刷新 (City、Address、Order、NewUser)']);
    }


    /**
     * 刷新清空缓存
     *
     */
    public function clearCache()
    {
        // 清空所有缓存
        Cache::clear();

        return json(['code' => 200, 'msg' => '缓存已清空']);
    }
}
